package router

import (
	"fmt"
	"gitee.com/aldrice/monitor/ent"
	"gitee.com/aldrice/monitor/pkg/logging"
	"github.com/labstack/echo/v4"
	"go.uber.org/zap"
	"net/http"
)

// apiError API Errors
type apiError struct {
	// in: body
	Code int    `json:"code"`
	Msg  string `json:"msg"`
}

func (e apiError) Error() string {
	return fmt.Sprintf("%d: %s", e.Code, e.Msg)
}

func ApiError(code int, msg string) *apiError {
	return &apiError{Code: code, Msg: msg}
}

// Standard Exceptions
type apiException struct {
	HttpCode int
	Internal apiError
}

func (s apiException) Error() string {
	return s.Internal.Error()
}

// ApiException writes standard error result to http response.
// Meaning this call is failure with server's problem.
func ApiException(httpCode int, code int, msg string) *apiException {
	return &apiException{HttpCode: httpCode, Internal: apiError{Code: code, Msg: msg}}
}

func HttpErrorHandler(oriErr error, c echo.Context) {
	{
		apiErr, ok := oriErr.(*apiError)
		if ok {
			c.Logger().Warn()
			logging.Logger().Warn("api return error",
				zap.String("uri", c.Request().RequestURI), zap.Error(apiErr))
			_ = c.JSON(http.StatusOK, apiErr)
			return
		}
		apiExc, ok := oriErr.(*apiException)
		if ok {
			logging.Logger().Warn("api return exception",
				zap.String("uri", c.Request().RequestURI), zap.Error(apiErr))
			_ = c.JSON(apiExc.HttpCode, &apiExc.Internal)
			return
		}
	}

	//deal other err
	var httpCode = 500
	rErr := &apiError{Msg: "出现未知问题，请联系我们进行处理: "}
	httpErr, ok := oriErr.(*echo.HTTPError)
	if ok {
		httpCode = httpErr.Code
		rErr.Code = 10001
		rErr.Msg += httpErr.Error()
	} else if ent.IsNotFound(oriErr) {
		httpCode = http.StatusNotFound
		rErr.Code = 10002
		rErr.Msg = "找不到此数据: " + oriErr.Error()
	} else {
		rErr.Code = 10003
		rErr.Msg += oriErr.Error()
	}
	logging.Logger().Error("api caused unexpected error",
		zap.String("uri", c.Request().RequestURI), zap.Error(rErr))
	_ = c.JSON(httpCode, rErr)

}
